﻿using Microsoft.Office.InfoPath;
using System;

namespace InfoPathHelpers.Validation
{
    /// <summary>
    /// Provides a number of methods for validating different data types.
    /// Note: These methods should only be called from a validation event.
    /// </summary>
    public static partial class ValidationHelper
    {
        /// <summary>
        /// Provides validation for the data type of a field.
        /// </summary>
        /// <param name="eventArgs">The XmlValidatingEventArgs of the validation event</param>
        /// <param name="type">The valid type for this field.</param>
        /// <returns>True if the field's value is a valid date; otherwise false.</returns>
        public static bool IsOfType(XmlValidatingEventArgs eventArgs, ValidatedTypes type)
        {
            return IsOfType(eventArgs, type, false, false);
        }

        /// <summary>
        /// Provides validation for the data type of a field
        /// with the option to show dialog to the user for failures.
        /// </summary>
        /// <param name="eventArgs">The XmlValidatingEventArgs of the validation event</param>
        /// <param name="type">The valid type for this field.</param>
        /// <param name="allowBlanks">A boolean value indicating whether or not the field can be empty.</param>
        /// <param name="showDialog">A boolean value indicating whether or not to show the user a message on validation failure.</param>
        /// <returns>True if the field's value is a valid date; otherwise false.</returns>
        public static bool IsOfType(XmlValidatingEventArgs eventArgs, ValidatedTypes type, bool allowBlanks, bool showDialog)
        {
            return IsOfType(eventArgs, type, allowBlanks, showDialog,
                new ValidationMessage()
                {
                    Caption = "Invalid Entry",
                    Message = "The value must be a valid " + type.ToString(),
                    MessageDetails = "This field must contain a valid date.",
                },
                new ValidationMessage()
                {
                    Caption = "Blank Entry",
                    Message = "Cannot be blank.",
                    MessageDetails = "This field must contain a valid date.",
                }
            );
        }

        /// <summary>
        /// Provides validation for the data type of a field
        /// with the option to show a custom dialog to the user for failures.
        /// </summary>
        /// <param name="eventArgs">The XmlValidatingEventArgs of the validation event</param>
        /// <param name="type">The valid type for this field.</param>
        /// <param name="allowBlanks">A boolean value indicating whether or not the field can be empty.</param>
        /// <param name="showDialog">A boolean value indicating whether or not to show the user a message on validation failure.</param>
        /// <param name="blankMessage">A ValidationMessage containing the message to be 
        /// displayed in event of validation failure.</param>
        /// <param name="invalidMessage">A ValidationMessage containing the message to be 
        /// displayed for blank entries (if not allowed).</param>
        /// <returns>True if the field's value is a valid date; otherwise false.</returns>
        public static bool IsOfType(XmlValidatingEventArgs eventArgs, ValidatedTypes type, bool allowBlanks, bool showDialog, ValidationMessage invalidMessage, ValidationMessage blankMessage)
        {
            // Delete operations or unspecififed operations are not validated so just return true.
            if (eventArgs.Operation == XmlOperation.Delete || eventArgs.Operation == XmlOperation.None)
                return true;

            // Insert operations do not use the New/OldValue parameters of XmlValidatingEventArgs
            // so we need to use the Value of the underlying xml element.
            string Value = eventArgs.Site.Value;

            bool IsEmpty = string.IsNullOrEmpty(Value);
            bool IsOfType = false;

            switch (type)
            {
                case ValidatedTypes.Integer:
                    int IntValue;
                    IsOfType = int.TryParse(Value, out IntValue);
                    break;
                case ValidatedTypes.Double:
                    double DoubleValue;
                    IsOfType = double.TryParse(Value, out DoubleValue);
                    break;
                case ValidatedTypes.Boolean:
                    bool BooleanValue;
                    IsOfType = bool.TryParse(Value, out BooleanValue);
                    break;
                case ValidatedTypes.Date:
                case ValidatedTypes.Time:
                case ValidatedTypes.DateTime:
                    DateTime DateValue;
                    IsOfType = DateTime.TryParse(Value, out DateValue);
                    break;
            }

            // If the field is not empty and the value is not a valid DateTime then validation has failed.
            if (!IsEmpty && !IsOfType)
            {
                // If the field is not empty and the value is not a valid email address then validation has failed.
                // So we report failure using "invalidMessage".
                HandleValidationFailure(eventArgs, invalidMessage, showDialog);
                // And of course return false because validation failed.
                return false;
            }
            // If the value is empty but validation does not allow blanks then validation fails.
            else if (IsEmpty && !allowBlanks)
            {
                // If the value is empty but validation does not allow blanks then validation fails.
                // So we report failure using the "blankMessage".
                HandleValidationFailure(eventArgs, blankMessage, showDialog);
                // And of course return false because validation failed.
                return false;
            }

            // Otherwise either the field is empty or a valid date so validation succeeded.
            return true;
        }
    }
}
